#include "hash_sequencial.h"

#define HASH_TERM 1831

hash * new_hash() {

	int i = 0;
	
	hash *H = (hash*)malloc(sizeof(hash));
	H->hash_table = (node**)malloc(sizeof(node*)*HASH_TERM);
	
	for ( i = 0; i < HASH_TERM; i++ ) {
		H->hash_table[i] = (node*)malloc(sizeof(node));
		H->hash_table[i] = NULL;
	}

	H->size = HASH_TERM;

	return H;

}
node * new_node(char *str) {

	node *N = (node*)malloc(sizeof(node));
	strcpy(N->arg, str);
	N->next = NULL;

	return N;

}

int hash_function(char *str) {

	int i = 0;
	int n = strlen(str);
	int ascii_sum = 0;
	int k_hash;

	for ( i; i < n; i++ )
		ascii_sum += ((int) str[i]) * i;
	
	k_hash = ascii_sum % HASH_TERM;

	return k_hash;

}

void alloc_node(node *N, hash *H) {	

	int k_hash = hash_function(N->arg);
	node * aux;
	
	if (H->hash_table[k_hash] == NULL)
		H->hash_table[k_hash] = N;
	else {
		aux = H->hash_table[k_hash];
		H->hash_table[k_hash] = N;
		H->hash_table[k_hash]->next = aux;
		
	}
	H->n_element++;
}

node * find_node(char *str, hash *H) {

	int k_hash = hash_function(str);
	node *aux = H->hash_table[k_hash];

	while (aux != NULL) {

		if (strcmp(str,aux->arg) == 0)
			break;
		else
			aux = aux->next;

	}

	return aux;

}

int rm_node(char *str, hash *H) {

	int k_hash = hash_function(str);
	node *aux = H->hash_table[k_hash];
	node *aux2;

	if ( aux != NULL ) {

		if (strcmp(str,aux->arg) == 0) {

				H->hash_table[k_hash] = H->hash_table[k_hash]->next;
				aux->next = NULL;
				free(aux);
				H->n_element--;
				return 1;
		
		} else {

			while (aux->next != NULL) {

				if (strcmp(str,aux->next->arg) == 0)
					break;
				else
					aux = aux->next;

			}

			if (aux->next != NULL) {

				aux2 = aux->next;
				aux->next = aux2->next;
				aux2->next = NULL;
				free(aux2);
				H->n_element--;
				return 1;

			}
			else return 0;

		}

	} 
	else return 0;

}

void clear_list(node *first) {

	node *aux = first;

	while (first != NULL) {

		first = first->next;
		aux->next = NULL;
		free(aux->arg);
		free(aux);
		aux = first;

	}

}

void clear_hash(hash *H) {

	int i = 0;

	for ( i = 0; i < H->size; i++ )
		clear_list(H->hash_table[i]);

	free(H->hash_table);
	free(H);

}

void print_hash(hash *H) {

	int i = 0;
	node *aux;

	for ( i = 0; i < H->size; i++ ) {

		aux =  H->hash_table[i];
		printf("%d: ", i);

		while (aux != NULL) {
			printf("%s ", aux->arg);
			aux = aux->next;
		}

		printf("\n");

	}

}
